home *** CD-ROM | disk | FTP | other *** search
/ PCMania 44 / PCMania CD44_1.iso / pcmania / treal44 / 3dtoshi / 3d.cpp next >
C/C++ Source or Header  |  1995-12-03  |  66KB  |  2,214 lines

  1.  
  2. // 3d.cpp
  3. //
  4. // Copyright (c) 1995 by Toshiaki Tsuji, all rights reserved.
  5.  
  6. #include "stdgui.h"
  7. #include "3d.h"
  8. #include <math.h>
  9. #include <search.h>
  10.  
  11. #define MIN_Z_DISTANCE 10
  12.  
  13. LONG NumShadeLevels=(LONG)1;
  14. LONG MaxShadeNumber=(LONG)1<<8;
  15.  
  16. //*************************************************
  17. //
  18. // Matrix Operations
  19. //
  20. //*************************************************
  21.  
  22. VOID InitMatrix ( MATRIX Matrix )
  23.   {
  24.     INT i,j;
  25.     for (i=0;i<4;i++)
  26.       {
  27.         for (j=0;j<4;j++)
  28.           {
  29.             if (i==j)
  30.               Matrix[i][j] = 1;
  31.             else    
  32.               Matrix[i][j] = 0;
  33.           } // End for  
  34.       } // End for  
  35.   } // End of InitMatrix
  36.  
  37. VOID CopyMatrix ( MATRIX Dest, MATRIX Src )
  38.   {
  39.     INT i,j;
  40.     for (i=0;i<4;i++)
  41.       {
  42.         for (j=0;j<4;j++)
  43.           {
  44.             Dest[i][j] = Src[i][j];  
  45.           } // End for  
  46.       } // End for  
  47.   } // End of CopyMatrix
  48.  
  49. VOID MultMatrix ( MATRIX Dest, MATRIX Mat1, MATRIX Mat2 )
  50.   {
  51.     INT i,j,k;
  52.  
  53.     for (i=0;i<4;i++)
  54.       {
  55.         for (j=0;j<4;j++)
  56.           {
  57.             Dest[i][j] = 0;  
  58.             for (k=0;k<4;k++)
  59.               {
  60.                 Dest[i][j] += Mat1[i][k]*Mat2[k][j];  
  61.               } // End for
  62.           } // End for
  63.       } // End for
  64.   } // End of MultMatrix    
  65.  
  66. VOID Translate ( MATRIX Matrix, double x, double y, double z )
  67.   {
  68.     MATRIX TMat;
  69.     MATRIX Mat1;
  70.  
  71.     TMat[0][0]=  1; TMat[0][1]=  0; TMat[0][2]=  0; TMat[0][3]=  0;
  72.     TMat[1][0]=  0; TMat[1][1]=  1; TMat[1][2]=  0; TMat[1][3]=  0;
  73.     TMat[2][0]=  0; TMat[2][1]=  0; TMat[2][2]=  1; TMat[2][3]=  0;
  74.     TMat[3][0]=  x; TMat[3][1]=  y; TMat[3][2]=  z; TMat[3][3]=  1;
  75.  
  76.     MultMatrix ( Mat1, Matrix, TMat );
  77.     CopyMatrix ( Matrix, Mat1 ); 
  78.   } // End of Translet for G3DENGINE
  79.  
  80. VOID Rotate ( MATRIX Matrix, double xa, double ya, double za )
  81.   {
  82.     MATRIX XMat,YMat,ZMat,Mat1,Mat2;
  83.     double Xa,Ya,Za;
  84.     double Sx,Cx,Sy,Cy,Sz,Cz;
  85.  
  86.     // Change degree to radian
  87.     Xa = xa*6.281/360;
  88.     Ya = ya*6.281/360;
  89.     Za = za*6.281/360;
  90.     
  91.     Sx = sin ( Xa );
  92.     Cx = cos ( Xa );
  93.     Sy = sin ( Ya );
  94.     Cy = cos ( Ya );
  95.     Sz = sin ( Za );
  96.     Cz = cos ( Za );
  97.  
  98.     XMat[0][0]=  1; XMat[0][1]=  0; XMat[0][2]=  0; XMat[0][3]=  0;
  99.     XMat[1][0]=  0; XMat[1][1]= Cx; XMat[1][2]= Sx; XMat[1][3]=  0;
  100.     XMat[2][0]=  0; XMat[2][1]=-Sx; XMat[2][2]= Cx; XMat[2][3]=  0;
  101.     XMat[3][0]=  0; XMat[3][1]=  0; XMat[3][2]=  0; XMat[3][3]=  1;
  102.     
  103.     YMat[0][0]= Cy; YMat[0][1]=  0; YMat[0][2]=-Sy; YMat[0][3]=  0;
  104.     YMat[1][0]=  0; YMat[1][1]=  1; YMat[1][2]=  0; YMat[1][3]=  0;
  105.     YMat[2][0]= Sy; YMat[2][1]=  0; YMat[2][2]= Cy; YMat[2][3]=  0;
  106.     YMat[3][0]=  0; YMat[3][1]=  0; YMat[3][2]=  0; YMat[3][3]=  1;
  107.     
  108.     ZMat[0][0]= Cz; ZMat[0][1]= Sz; ZMat[0][2]=  0; ZMat[0][3]=  0;
  109.     ZMat[1][0]=-Sz; ZMat[1][1]= Cz; ZMat[1][2]=  0; ZMat[1][3]=  0;
  110.     ZMat[2][0]=  0; ZMat[2][1]=  0; ZMat[2][2]=  1; ZMat[2][3]=  0;
  111.     ZMat[3][0]=  0; ZMat[3][1]=  0; ZMat[3][2]=  0; ZMat[3][3]=  1;
  112.  
  113.     MultMatrix ( Mat1, Matrix, XMat );
  114.     MultMatrix ( Mat2, Mat1, YMat );
  115.     MultMatrix ( Matrix, Mat2, ZMat );
  116.   } // End of Rotate for G3DENGINE
  117.  
  118.  
  119. //*************************************************
  120. //
  121. // 3D Light 
  122. //
  123. //*************************************************
  124.  
  125. G3DLIGHT::G3DLIGHT ()
  126.   {
  127.   } // End of Constructor for G3DLIGHT
  128.  
  129. G3DLIGHT::~G3DLIGHT ()
  130.   {
  131.   } // End of Destructor for G3DLIGHT
  132.  
  133. VOID G3DLIGHT::SetPosition ( double x, double y, double z )
  134.   {
  135.     Position.x = x;  
  136.     Position.y = y;  
  137.     Position.z = z;  
  138.   } // End of SetPosition for G3DLIGHT
  139.  
  140. VOID G3DLIGHT::SetDirection ( double x, double y, double z )
  141.   {
  142.     double Magnitude;
  143.  
  144.     Magnitude = x*x+y*y+z*z;
  145.     Magnitude = sqrt ( Magnitude );
  146.  
  147.     if (Magnitude!=0)
  148.       {  
  149.         Direction.x = x/Magnitude;  
  150.         Direction.y = y/Magnitude;  
  151.         Direction.z = z/Magnitude;
  152.       } // End if
  153.     else  
  154.       {  
  155.         Direction.x = x;  
  156.         Direction.y = y;  
  157.         Direction.z = z;
  158.       } // End if  
  159.   } // End of SetDirection for G3DLIGHT
  160.  
  161.  
  162. //*************************************************
  163. //
  164. // 3D Object 
  165. //
  166. //*************************************************
  167.  
  168. G3DOBJECT::G3DOBJECT ()
  169.   {
  170.     NumPoints = 0;
  171.     Local3DList = NULL;
  172.     World3DList = NULL;
  173.     Camera3DList = NULL;
  174.     PointNormalList = NULL;
  175.     PointCountList = NULL;
  176.     IntensityList = NULL;
  177.     Scr2DList = NULL;
  178.     NumMeshes = 0;
  179.     MeshList = NULL;
  180.     Position.x = 0;
  181.     Position.y = 0;
  182.     Position.z = 0;
  183.     Angle.x = 0;
  184.     Angle.y = 0;
  185.     Angle.z = 0;
  186.   } // End of Constructor for G3DOBJECT  
  187.  
  188. G3DOBJECT::~G3DOBJECT ()
  189.   {
  190.     if (Local3DList!=NULL)
  191.       {
  192.         delete Local3DList;
  193.         Local3DList = NULL;  
  194.       } // End if
  195.     if (World3DList!=NULL)
  196.       {
  197.         delete World3DList;
  198.         World3DList = NULL;  
  199.       } // End if
  200.     if (Camera3DList!=NULL)
  201.       {
  202.         delete Camera3DList;
  203.         Camera3DList = NULL;  
  204.       } // End if
  205.     if (PointNormalList!=NULL)
  206.       {
  207.         delete PointNormalList;
  208.         PointNormalList = NULL;  
  209.       } // End if
  210.     if (PointCountList!=NULL)
  211.       {
  212.         delete PointCountList;
  213.         PointCountList = NULL;  
  214.       } // End if
  215.     if (IntensityList!=NULL)
  216.       {
  217.         delete IntensityList;
  218.         IntensityList = NULL;  
  219.       } // End if
  220.     if (Scr2DList!=NULL)
  221.       {
  222.         delete Scr2DList;
  223.         Scr2DList = NULL;  
  224.       } // End if
  225.     if (MeshList!=NULL)
  226.       {
  227.         delete MeshList;
  228.         MeshList = NULL;  
  229.       } // End if      
  230.   } // End of Destructor for G3DOBJECT  
  231.  
  232. BOOLEAN G3DOBJECT::CreatePoints ( LONG Num )
  233.   {
  234.     if (Local3DList!=NULL)
  235.       delete Local3DList;
  236.     Local3DList = new POINT3D [Num];
  237.     if (Local3DList==NULL)
  238.       return FAILURE;
  239.       
  240.     if (World3DList!=NULL)
  241.       delete World3DList;
  242.     World3DList = new POINT3D [Num];
  243.     if (World3DList==NULL)
  244.       return FAILURE;
  245.       
  246.     if (Camera3DList!=NULL)
  247.       delete Camera3DList;
  248.     Camera3DList = new POINT3D [Num];
  249.     if (Camera3DList==NULL)
  250.       return FAILURE;
  251.     
  252.     if (PointNormalList!=NULL)
  253.       delete PointNormalList;
  254.     PointNormalList = new POINT3D [Num];
  255.     if (PointNormalList==NULL)
  256.       return FAILURE;
  257.     
  258.     if (PointCountList!=NULL)
  259.       delete PointCountList;
  260.     PointCountList = new BYTE [Num];
  261.     if (PointCountList==NULL)
  262.       return FAILURE;
  263.     
  264.     if (IntensityList!=NULL)
  265.       delete IntensityList;
  266.     IntensityList = new LONG [Num];
  267.     if (IntensityList==NULL)
  268.       return FAILURE;
  269.     
  270.     if (Scr2DList!=NULL)
  271.       delete Scr2DList;
  272.     Scr2DList = new POINT2D [Num];
  273.     if (Scr2DList==NULL)
  274.       return FAILURE;
  275.       
  276.     NumPoints = Num;
  277.  
  278.     return SUCCESS;  
  279.   } // End of CreatePoints for G3DOBJECT
  280.  
  281. BOOLEAN G3DOBJECT::CreateMeshes ( LONG Num )
  282.   {
  283.     if (MeshList!=NULL)
  284.       delete MeshList;
  285.     MeshList = new MESH3D [Num];
  286.     if (MeshList==NULL)
  287.       return FAILURE;
  288.  
  289.     LONG i;
  290.  
  291.     for (i=0;i<Num;i++)
  292.       {
  293.         MeshList[i].Flags = 0;  
  294.       } // End for
  295.       
  296.     NumMeshes = Num;  
  297.     return SUCCESS;  
  298.   } // End of CreateMeshes for G3DOBJECT
  299.  
  300. VOID G3DOBJECT::TransformLocalToWorld ( MATRIX Matrix )
  301.   {
  302.     LONG i;
  303.     for (i=0;i<NumPoints;i++)
  304.       {
  305.         double x,y,z;
  306.         x = Local3DList[i].x;
  307.         y = Local3DList[i].y;
  308.         z = Local3DList[i].z;
  309.         World3DList[i].x = x * Matrix[0][0] +
  310.                             y * Matrix[1][0] +  
  311.                              z * Matrix[2][0] +  
  312.                               Matrix[3][0] + Position.x;
  313.         World3DList[i].y = x * Matrix[0][1] +
  314.                             y * Matrix[1][1] +  
  315.                              z * Matrix[2][1] +  
  316.                               Matrix[3][1] + Position.y;
  317.         World3DList[i].z = x * Matrix[0][2] +
  318.                             y * Matrix[1][2] +  
  319.                              z * Matrix[2][2] +  
  320.                               Matrix[3][2] + Position.z;
  321.       } // End for
  322.   } // End of TransformLocalToWorld for G3DOBJECT
  323.  
  324. VOID G3DOBJECT::TransformWorldToCamera ( MATRIX Matrix )
  325.   {
  326.     LONG i;
  327.     double cz;
  328.     for (i=0;i<NumPoints;i++)
  329.       {
  330.         double x,y,z;
  331.         x = World3DList[i].x;
  332.         y = World3DList[i].y;
  333.         z = World3DList[i].z;
  334.  
  335.         Camera3DList[i].x = x * Matrix[0][0] +
  336.                              y * Matrix[1][0] +  
  337.                               z * Matrix[2][0] +  
  338.                                Matrix[3][0];
  339.         Camera3DList[i].y = x * Matrix[0][1] +
  340.                              y * Matrix[1][1] +  
  341.                               z * Matrix[2][1] +  
  342.                                Matrix[3][1];
  343.         cz = Camera3DList[i].z = x * Matrix[0][2] +
  344.                              y * Matrix[1][2] +  
  345.                               z * Matrix[2][2] +  
  346.                                Matrix[3][2];
  347.         if (i==0)
  348.           MinZ = MaxZ = cz;
  349.         else
  350.           {
  351.             if (cz<MinZ)
  352.               MinZ = cz;
  353.             else if (cz>MaxZ)
  354.               MaxZ = cz;  
  355.           } // End else                                                      
  356.       } // End for      
  357.   } // End of TransformWorldToCamera for G3DOBJECT
  358.  
  359. VOID G3DOBJECT::Project ( LONG Distance )
  360.   {
  361.     LONG i;
  362.     for (i=0;i<NumPoints;i++)
  363.       {
  364.         double z;
  365.         z = Camera3DList[i].z;
  366.         if (z == 0)
  367.           z = 0.1;  
  368.         Scr2DList[i].x = Camera3DList[i].x*Distance / z;  
  369.         Scr2DList[i].y = - (Camera3DList[i].y*Distance / z);  
  370.       } // End for  
  371.   } // End of Project for G3DOBJECT
  372.  
  373. VOID G3DOBJECT::SetPosition ( double x, double y, double z )
  374.   {
  375.     Position.x = x;  
  376.     Position.y = y;  
  377.     Position.z = z;  
  378.   } // End of SetPosition for G3DOBJECT
  379.  
  380. VOID G3DOBJECT::SetAngle ( double xa, double ya, double za )
  381.   {
  382.     Angle.x = xa;  
  383.     Angle.y = ya;  
  384.     Angle.z = za;  
  385.   } // End of SetAngle for G3DOBJECT
  386.  
  387. VOID G3DOBJECT::Move ( double x, double y, double z,
  388.                        double xa, double ya, double za )
  389.   {
  390.     MATRIX Matrix;
  391.  
  392.     Position.x += x;
  393.     Position.y += y;
  394.     Position.z += z;
  395.  
  396.     Angle.x += xa;
  397.     Angle.y += ya;
  398.     Angle.z += za;
  399.     
  400.     InitMatrix ( Matrix );
  401.  
  402.     Rotate ( Matrix, -Angle.x, -Angle.y, -Angle.z );
  403.  
  404.     TransformLocalToWorld ( Matrix );
  405.   } // End of Move for G3DOBJECT                       
  406.  
  407. VOID G3DOBJECT::GetMeshNormal ( MESH3D *Mesh )
  408.   {
  409.     double A,B,C;  
  410.     double x1,y1,z1,x2,y2,z2,x3,y3,z3;
  411.     LONG *List;
  412.     LONG List0,List1,List2;
  413.  
  414.     List = Mesh->Points;
  415.     List0 = List[0];
  416.     List1 = List[1];
  417.     List2 = List[2];
  418.  
  419.     x1 = Camera3DList[List0].x;
  420.     y1 = Camera3DList[List0].y;
  421.     z1 = Camera3DList[List0].z;
  422.  
  423.     x2 = Camera3DList[List1].x;
  424.     y2 = Camera3DList[List1].y;
  425.     z2 = Camera3DList[List1].z;
  426.  
  427.     x3 = Camera3DList[List2].x;
  428.     y3 = Camera3DList[List2].y;
  429.     z3 = Camera3DList[List2].z;
  430.  
  431.     // Take a cross product of two vectors
  432.  
  433.     A = (y2-y1)*(z3-z1) - (z2-z1)*(y3-y1);
  434.     B = - ((x2-x1)*(z3-z1) - (z2-z1)*(x3-x1));
  435.     C = (x2-x1)*(y3-y1) - (y2-y1)*(x3-x1);
  436.  
  437.     if (Mesh->Flags&MESH_REVERSED)
  438.       {
  439.         A = -A;
  440.         B = -B;
  441.         C = -C;
  442.       } // End if
  443.  
  444.     double Magnitude = A*A + B*B + C*C;
  445.  
  446.     Magnitude = sqrt ( Magnitude );
  447.     if (Magnitude!=0)
  448.       {
  449.         A /= Magnitude;
  450.         B /= Magnitude;
  451.         C /= Magnitude;
  452.       } // End if
  453.  
  454.     Mesh->A = A;      
  455.     Mesh->B = B;      
  456.     Mesh->C = C;
  457.   } // End of GetMeshNormal for G3DOBJECT
  458.  
  459. BOOLEAN G3DOBJECT::MeshVisible ( LONG Index )
  460.   {
  461.     MESH3D *Mesh;
  462.     double z1,z2,z3;
  463.     double MeshMinZ,MeshMaxZ;
  464.     LONG *List;
  465.     LONG List0,List1,List2;
  466.  
  467.     Mesh = &(MeshList[Index]);
  468.     List = Mesh->Points;
  469.     List0 = List[0];
  470.     List1 = List[1];
  471.     List2 = List[2];
  472.  
  473.     MeshMinZ = MeshMaxZ = z1 = Camera3DList[List0].z;
  474.  
  475.     z2 = Camera3DList[List1].z;
  476.     if (z2<MeshMinZ)
  477.       MeshMinZ = z2;
  478.     else if (z2>MeshMaxZ)
  479.       MeshMaxZ = z2;
  480.  
  481.     z3 = Camera3DList[List2].z;
  482.     if (z3<MeshMinZ)
  483.       MeshMinZ = z3;
  484.     else if (z3>MeshMaxZ)
  485.       MeshMaxZ = z3;
  486.  
  487.     if (MeshMaxZ<MIN_Z_DISTANCE)
  488.       { 
  489.         Mesh->Flags &= ~MESH_VISIBLE;
  490.         return FALSE;
  491.       } // End if        
  492.       
  493.     GetMeshNormal ( Mesh );
  494.  
  495.     PointCountList[List0] ++;
  496.     PointNormalList[List0].x += Mesh->A;    
  497.     PointNormalList[List0].y += Mesh->B;    
  498.     PointNormalList[List0].z += Mesh->C;    
  499.       
  500.     PointCountList[List1] ++;
  501.     PointNormalList[List1].x += Mesh->A;    
  502.     PointNormalList[List1].y += Mesh->B;    
  503.     PointNormalList[List1].z += Mesh->C;    
  504.       
  505.     PointCountList[List2] ++;
  506.     PointNormalList[List2].x += Mesh->A;    
  507.     PointNormalList[List2].y += Mesh->B;    
  508.     PointNormalList[List2].z += Mesh->C;    
  509.       
  510.     Mesh->MinZ = MeshMinZ;
  511.     Mesh->MaxZ = MeshMaxZ;
  512.  
  513.     // Take a dot product
  514.       
  515.     double Product;
  516.     double x1,y1;
  517.  
  518.     x1 = Camera3DList[List0].x;
  519.     y1 = Camera3DList[List0].y;
  520.       
  521.     Product = Mesh->A*x1+Mesh->B*y1+Mesh->C*z1;
  522.     if (Product<0)
  523.       { 
  524.         Mesh->Flags &= ~MESH_VISIBLE;
  525.         return FALSE;
  526.       } // End if        
  527.       
  528.     Mesh->Flags |= MESH_VISIBLE;
  529.     return TRUE;    
  530.   } // End of MeshVisible for G3DOBJECT
  531.   
  532. VOID G3DOBJECT::ProcessMeshes ()
  533.   {
  534.     LONG i;
  535.  
  536.     for (i=0;i<NumPoints;i++)
  537.       {
  538.         PointCountList[i] = 0;  
  539.         PointNormalList[i].x = 0;  
  540.         PointNormalList[i].y = 0;  
  541.         PointNormalList[i].z = 0;  
  542.       } // End for
  543.       
  544.     for (i=0;i<NumMeshes;i++)
  545.       {
  546.         MeshVisible ( i );  
  547.       } // End for
  548.   } // End of ProcessMeshes
  549.   
  550. VOID G3DOBJECT::ComputePointIntensity ( G3DLIGHT **LightList )
  551.   {
  552.     LONG i;
  553.     G3DLIGHT *Light;
  554.     double Product;
  555.  
  556.     Light = LightList[LightSource];
  557.     
  558.     for (i=0;i<NumPoints;i++)
  559.       {
  560.         double Count;
  561.         double x,y,z;
  562.  
  563.         Count = (double)PointCountList[i];
  564.         x = PointNormalList[i].x;
  565.         y = PointNormalList[i].y;
  566.         z = PointNormalList[i].z;
  567.  
  568.         if (Count!=0)
  569.           {
  570.             x /= Count;  
  571.             y /= Count;  
  572.             z /= Count;  
  573.           } // End if
  574.           
  575.         // Do Cross Product
  576.         Product = x*Light->Direction.x+
  577.                    y*Light->Direction.y+
  578.                     z*Light->Direction.z;
  579.         LONG Level;
  580.         Level = Product*(MaxShadeNumber);
  581.         if (Level<0)
  582.           Level = 0;
  583.         else if (Level>(MaxShadeNumber-256))
  584.           Level = MaxShadeNumber-256;
  585.  
  586.         IntensityList[i] = Level;            
  587.       } // End for
  588.   } // End of ComputePointIntensity for G3DOBJECT
  589.  
  590. VOID G3DOBJECT::Init ()
  591.   {
  592.   } // End of Init for G3DOBJECT
  593.  
  594.  
  595. //*************************************************
  596. //
  597. // 3D World
  598. //
  599. //*************************************************
  600.  
  601. G3DWORLD::G3DWORLD ()
  602.   {
  603.     NumObjects = 0;
  604.     ObjectList = NULL;
  605.     NumLights = 0;
  606.     LightList = NULL;
  607.     TextureList = NULL;
  608.     NumTextures = 0;
  609.   } // End of Constructor for G3DWORLD
  610.  
  611. G3DWORLD::~G3DWORLD ()
  612.   {
  613.     LONG i;
  614.     
  615.     if (ObjectList!=NULL)
  616.       {
  617.         for (i=0;i<NumObjects;i++)
  618.           {
  619.             delete ObjectList[i];  
  620.           } // End for
  621.         delete ObjectList;
  622.       } // End if    
  623.     ObjectList = NULL;
  624.     
  625.     if (LightList!=NULL)
  626.       {
  627.         for (i=0;i<NumLights;i++)
  628.           {
  629.             delete LightList[i];  
  630.           } // End for
  631.         delete LightList;  
  632.       } // End if      
  633.     LightList = NULL;
  634.       
  635.     if (TextureList!=NULL)
  636.       {
  637.         for (i=0;i<NumTextures;i++)
  638.           {
  639.             delete TextureList[i];
  640.           } // End for
  641.         delete TextureList;
  642.         TextureList = NULL;
  643.       } // End if
  644.   } // End of Destructor for G3DWORLD
  645.  
  646. BOOLEAN G3DWORLD::CreateTextures ( LONG Num )
  647.   {
  648.     NumTextures = Num;
  649.     LONG i;
  650.     if (TextureList!=NULL)
  651.       {
  652.         for (i=0;i<NumTextures;i++)
  653.           delete TextureList[i];
  654.       } // End if
  655.     delete TextureList;
  656.     NumTextures = Num;
  657.     TextureList = new IMAGE * [NumTextures];
  658.     if (TextureList==NULL)
  659.       return FAILURE;
  660.     for (i=0;i<NumTextures;i++)
  661.       {
  662.         TextureList[i] = new IMAGE ();
  663.         if (TextureList[i]==NULL)
  664.           return FAILURE;
  665.       } // End for
  666.     return SUCCESS;
  667.   } // End of CreateTextures for G3DWORLD
  668.  
  669. BOOLEAN G3DWORLD::CreateObjects ( LONG Num )
  670.   {
  671.     INT i;
  672.     if (ObjectList!=NULL)
  673.       {
  674.         for (i=0;i<NumObjects;i++)
  675.           {
  676.             delete ObjectList[i];  
  677.           } // End for  
  678.         delete ObjectList;
  679.       } // End if  
  680.  
  681.     ObjectList = new G3DOBJECT* [Num];
  682.     if (ObjectList==NULL)
  683.       return FAILURE;
  684.     NumObjects = Num;
  685.     for (i=0;i<NumObjects;i++)
  686.       {
  687.         ObjectList[i] = new G3DOBJECT ();  
  688.       } // End for
  689.     return SUCCESS;
  690.   } // End of CreateObjects for G3DWORLD
  691.  
  692. BOOLEAN G3DWORLD::CreateLights ( LONG Num )
  693.   {
  694.     INT i;
  695.     if (LightList!=NULL)
  696.       {
  697.         for (i=0;i<NumLights;i++)
  698.           {
  699.             delete LightList[i];  
  700.           } // End for  
  701.         delete LightList;
  702.       } // End if  
  703.  
  704.     LightList = new G3DLIGHT* [Num];
  705.     if (LightList==NULL)
  706.       return FAILURE;
  707.     NumLights = Num;
  708.  
  709.     for (i=0;i<NumLights;i++)
  710.       {
  711.         LightList[i] = new G3DLIGHT ();  
  712.       } // End for
  713.     return SUCCESS;
  714.   } // End of CreateLights for G3DWORLD
  715.  
  716. LONG G3DWORLD::GetMeshIntensity ( G3DOBJECT *Object, MESH3D *Mesh )
  717.   {
  718.     double A,B,C;
  719.     G3DLIGHT *Light;
  720.  
  721.     Light = LightList[Object->GetLightSource ()];
  722.     A = Mesh->A;  
  723.     B = Mesh->B;  
  724.     C = Mesh->C;
  725.  
  726.     // Do Cross Product
  727.     double Product;
  728.     LONG Intensity;
  729.  
  730.     Product = A*Light->Direction.x+
  731.                B*Light->Direction.y+
  732.                 C*Light->Direction.z;
  733.  
  734.     if (Product<=0)
  735.       return 0;
  736.     else
  737.       {
  738.         Intensity = Product*MaxShadeNumber;
  739.         if (Intensity<0)
  740.           Intensity = 0;
  741.         else if (Intensity>MaxShadeNumber-256)
  742.           Intensity = MaxShadeNumber-256;
  743.       } // End else
  744.     return Intensity;
  745.   } // End of GetMeshIntensity for G3DWORLD
  746.   
  747.  
  748. //*************************************************
  749. //
  750. // 3D Viewer
  751. //
  752. //*************************************************
  753.  
  754. G3DCAMERA::G3DCAMERA ()
  755.   {
  756.     SetPosition ( 0, 0, 0 );  
  757.     SetAngle ( 0, 0, 0 );  
  758.   } // End of Constructor for G3DCAMERA
  759.  
  760. G3DCAMERA::~G3DCAMERA ()  
  761.   {
  762.   } // End of Destructor for G3DCAMERA
  763.  
  764. VOID G3DCAMERA::SetPosition ( double x, double y, double z )
  765.   {
  766.     Position.x = x;  
  767.     Position.y = y;  
  768.     Position.z = z;  
  769.   } // End of SetPosition for G3DCAMERA
  770.  
  771. VOID G3DCAMERA::SetAngle ( double xa, double ya, double za )
  772.   {
  773.     Angle.x = xa;  
  774.     Angle.y = ya;  
  775.     Angle.z = za;  
  776.   } // End of SetAngle for G3DCAMERA
  777.   
  778. VOID G3DCAMERA::MovePosition ( double x, double y, double z )
  779.   {
  780.     Position.x += x;  
  781.     Position.y += y;  
  782.     Position.z += z;  
  783.   } // End of MovePosition for G3DCAMERA
  784.   
  785. VOID G3DCAMERA::MoveAngle ( double xa, double ya, double za )
  786.   {
  787.     Angle.x += xa;  
  788.     Angle.y += ya;  
  789.     Angle.z += za;  
  790.   } // End of MoveAngle for G3DCAMERA
  791.  
  792.  
  793. //*************************************************
  794. //
  795. // 3D Graphics Engine
  796. //
  797. //*************************************************
  798.  
  799. G3DENGINE::G3DENGINE ()
  800.   {
  801.     Camera = new G3DCAMERA ();
  802.     World = NULL;
  803.     NumVisibleMeshes = 0;
  804.     VisibleMeshes = NULL;
  805.     ShadeTable = NULL;
  806.     ShadeMethod = SHADE_GOURAUD;
  807.     SurfaceMethod = SURFACE_TEXTURE;
  808.     TextureList = NULL;
  809.   } // End of Constructor for G3DENGINE
  810.  
  811. G3DENGINE::~G3DENGINE ()
  812.   {
  813.     if (Camera!=NULL)
  814.       delete Camera;
  815.     Camera = NULL;
  816.  
  817.     if (VisibleMeshes!=NULL)
  818.       delete VisibleMeshes;
  819.     VisibleMeshes = NULL;  
  820.     TextureList = NULL;
  821.   } // End of Destructor for G3DENGINE
  822.  
  823. VOID G3DENGINE::SetWorld ( G3DWORLD *NewWorld )
  824.   {
  825.     if (NewWorld==NULL)
  826.       return;
  827.       
  828.     World = NewWorld;
  829.  
  830.     LONG NumObjects;    
  831.     LONG i;
  832.     G3DOBJECT **ObjectList;
  833.     LONG NumMeshes;
  834.  
  835.     NumObjects = World->GetNumObjects ();
  836.     ObjectList = World->GetObjectList ();
  837.  
  838.     NumMeshes = 0;
  839.     for (i=0;i<NumObjects;i++)
  840.       {
  841.         NumMeshes += ObjectList[i]->GetNumMeshes ();
  842.         ObjectList[i]->Init ();
  843.         ObjectList[i]->Move ( 0, 0, 0, 0, 0, 0 );  
  844.       } // End for
  845.       
  846.     if (VisibleMeshes!=NULL)
  847.       delete VisibleMeshes;
  848.  
  849.     VisibleMeshes = new MESHNODE [NumMeshes*2];
  850.     TextureList = World->GetTextureList ();
  851.   } // End of SetWorld for G3DENGINE
  852.  
  853. VOID G3DENGINE::Transform ()
  854.   {
  855.     if (World==NULL)
  856.       return;
  857.  
  858.     LONG NumObjects;
  859.     G3DOBJECT **ObjectList;
  860.     NumObjects = World->GetNumObjects ();
  861.     ObjectList = World->GetObjectList ();
  862.     
  863.     LONG i;
  864.  
  865.     for (i=0;i<NumObjects;i++)
  866.       {
  867.         ObjectList[i]->TransformWorldToCamera ( MasterMatrix );  
  868.       } // End for
  869.   } // End of Transform for G3DENGINE
  870.  
  871. INT MIDDLEPOINTTABLE[3][3] = { { 1, 2, 1 }, { 2, 0, 0 }, { 1, 0, 0 } };
  872.                                         
  873. typedef VOID (*DrawMeshType) ( BYTE *Buffer, LONG AddDest, BYTE Color, LONG Length );
  874.     
  875. VOID G3DENGINE::DrawTriMesh ( IMAGE *Dest, DRAWPOINT2D *Points, BYTE Color,
  876.                               IMAGE *Image, LONG ILevel, LONG Flags )
  877.   {
  878.     LONG MinX,MaxX,MinY,MaxY;
  879.     LONG i,High,Middle,Low;
  880.  
  881.     // Sort the Points in order of high to low in y coord.
  882.     MinX = MaxX = Points[0].x;
  883.     MinY = MaxY = Points[0].y;
  884.     Low = High = 0;
  885.  
  886.     for (i=1;i<3;i++)
  887.       {
  888.         LONG x,y;
  889.         x = Points[i].x;
  890.         y = Points[i].y;
  891.         if (x<MinX)
  892.           MinX = x;
  893.         else if (x>MaxX)
  894.           MaxX = x;
  895.             
  896.         if (y<MinY)
  897.           {
  898.             MinY = y;
  899.             High = i;
  900.           } // End if  
  901.         else if (y>MaxY)
  902.           {
  903.             MaxY = y;
  904.             Low = i;
  905.           } // End if  
  906.       } // End for
  907.  
  908.     RECTANGLE ViewPort;
  909.     BOOLEAN Clipped = FALSE;
  910.  
  911.     ViewPort = Dest->GetViewPort ();
  912.  
  913.     // Check for if clipping is necessary
  914.     if (MinX>ViewPort.x2)
  915.       return;
  916.     if (MinY>ViewPort.y2)
  917.       return;
  918.     if (MaxX<ViewPort.x1)
  919.       return;
  920.     if (MaxY<ViewPort.y1)
  921.       return;
  922.       
  923.     if (MinX<ViewPort.x1)
  924.       {
  925.         Clipped = TRUE;
  926.         SetViewRegion ( ViewPort.x1, ViewPort.x2 );
  927.       } // End if  
  928.     else if (MaxX>ViewPort.x2)
  929.       {
  930.         Clipped = TRUE;
  931.         SetViewRegion ( ViewPort.x1, ViewPort.x2 );
  932.       } // End else if  
  933.       
  934.     Middle = MIDDLEPOINTTABLE[High][Low];      
  935.  
  936.     INT Case;
  937.     
  938.     if (Points[Low].y==Points[Middle].y)
  939.       Case = 1; 
  940.     else if (Points[High].y==Points[Middle].y)
  941.       Case = 2;
  942.     else
  943.       {
  944.         Case = 3;   
  945.       } // End else
  946.  
  947.     LONG Length,Diff;
  948.     LONG StartY;
  949.     LONG x1,x2,x3,x4;
  950.     LONG u1,u2,u3,u4;
  951.     LONG v1,v2,v3,v4;
  952.     LONG I1,I2,I3,I4;
  953.     LONG Dx1,Dx2,Dx3,Dx4;
  954.     LONG DI1,DI2,DI3,DI4;
  955.     LONG Du1,Du2,Du3,Du4;
  956.     LONG Dv1,Dv2,Dv3,Dv4;
  957.     LONG Dy1,Dy2,Dy3;
  958.     INT  Left,Right;
  959.  
  960.     BYTE *Buffer;
  961.     LONG Temp;
  962.     BOOLEAN IsTexture,IsGouraud,IsFlat;
  963.     DrawMeshType DrawMesh;
  964.  
  965.     if (Flags&MESH_FLAT)
  966.       IsFlat = TRUE;
  967.     else
  968.       IsFlat = FALSE;  
  969.       
  970.     if (Flags&MESH_GOURAUD)
  971.       IsGouraud = TRUE;
  972.     else
  973.       IsGouraud = FALSE;  
  974.       
  975.     if (Flags&MESH_TEXTURE)
  976.       IsTexture = TRUE;
  977.     else
  978.       IsTexture = FALSE;  
  979.  
  980.     if (IsTexture)
  981.       {
  982.         if (Clipped)
  983.           {
  984.             if (IsGouraud)
  985.               DrawMesh = DrawClippedGTex;
  986.             else if (IsFlat)    
  987.               DrawMesh = DrawClippedFTex;
  988.             else
  989.               DrawMesh = DrawClippedTex;  
  990.           } // End if
  991.         else
  992.           {
  993.             if (IsGouraud)
  994.               DrawMesh = DrawGTexTriangle;
  995.             else if (IsFlat)
  996.               {
  997.                 SetFShadeTable ( ShadeTable->GetTable() + (ILevel&0xFF00) );
  998.                 DrawMesh = DrawFTexTriangle;
  999.               } // End else if  
  1000.             else
  1001.               DrawMesh = DrawTexTriangle;  
  1002.           } // End else  
  1003.       } // End if
  1004.     else 
  1005.       {
  1006.         if (Clipped)
  1007.           {
  1008.             if (IsGouraud)
  1009.               DrawMesh = DrawClippedGShade;
  1010.             else
  1011.               DrawMesh = DrawClippedTriangle;  
  1012.           } // End if
  1013.         else
  1014.           {
  1015.             if (IsGouraud)
  1016.               DrawMesh = DrawGShadeTriangle;
  1017.             else
  1018.               DrawMesh = DrawSimpleTriangle;  
  1019.           } // End else  
  1020.       } // End else 
  1021.       
  1022.     switch (Case)
  1023.       {
  1024.         case 1 :
  1025.           if (Points[Middle].x<=Points[Low].x)
  1026.             {
  1027.               Left = Middle;
  1028.               Right = Low;
  1029.             } // End if
  1030.           else
  1031.             {
  1032.               Left = Low;
  1033.               Right = Middle;
  1034.             } // End if
  1035.  
  1036.           Dx1 = (Points[Left].x-Points[High].x)<<16;
  1037.           Dx2 = (Points[Right].x-Points[High].x)<<16;
  1038.  
  1039.           Dy1 = Points[Left].y-Points[High].y+1;
  1040.           Dy2 = Points[Right].y-Points[High].y+1;
  1041.  
  1042.           Dx1 = Dx1 / Dy1;
  1043.           Dx2 = Dx2 / Dy2;
  1044.           
  1045.           x1 = Points[High].x <<16;
  1046.           x2 = x1;
  1047.  
  1048.           if (IsTexture)
  1049.             {
  1050.               Du1 = ((LONG)Points[Left].u-Points[High].u)<<16;
  1051.               Du2 = ((LONG)Points[Right].u-Points[High].u)<<16;
  1052.               Dv1 = ((LONG)Points[Left].v-Points[High].v)<<16;
  1053.               Dv2 = ((LONG)Points[Right].v-Points[High].v)<<16;
  1054.               
  1055.               Du1 = Du1 / Dy1;
  1056.               Du2 = Du2 / Dy2;
  1057.               Dv1 = Dv1 / Dy1;
  1058.               Dv2 = Dv2 / Dy2;
  1059.               
  1060.               u1 = (LONG)Points[High].u << 16;
  1061.               u2 = u1;
  1062.               v1 = (LONG)Points[High].v << 16;
  1063.               v2 = v1;          
  1064.             } // End if
  1065.                 
  1066.           if (IsGouraud)
  1067.             {
  1068.               DI1 = ((LONG)Points[Left].Intensity-(LONG)Points[High].Intensity)<<16;
  1069.               DI2 = ((LONG)Points[Right].Intensity-(LONG)Points[High].Intensity)<<16;
  1070.           
  1071.               DI1 = DI1 / Dy1;
  1072.               DI2 = DI2 / Dy2;
  1073.               
  1074.               I1 = (LONG)Points[High].Intensity << 16;
  1075.               I2 = I1;          
  1076.             } // End if  
  1077.           
  1078.           Length = Points[Low].y-Points[High].y+1;
  1079.           Diff = 0;
  1080.           if (Points[High].y<ViewPort.y1)
  1081.             {
  1082.               Diff = ViewPort.y1-Points[High].y;
  1083.               StartY = ViewPort.y1;
  1084.               Length -= Diff;
  1085.               x1 += Dx1*Diff;             
  1086.               x2 += Dx2*Diff;
  1087.  
  1088.               if (IsTexture)
  1089.                 {
  1090.                   u1 += Du1*Diff;             
  1091.                   u2 += Du2*Diff;              
  1092.                   v1 += Dv1*Diff;             
  1093.                   v2 += Dv2*Diff;
  1094.                 } // End if   
  1095.  
  1096.               if (IsGouraud)
  1097.                 {
  1098.                   I1 += DI1*Diff;             
  1099.                   I2 += DI2*Diff;
  1100.                 } // End if  
  1101.             } // End if
  1102.           else
  1103.             StartY = Points[High].y;
  1104.  
  1105.           if (Points[Low].y>ViewPort.y2)
  1106.             Length -= Points[Low].y - ViewPort.y2;
  1107.             
  1108.           if (Length>0)
  1109.             {  
  1110.               SetLeftRight ( x1, x2, Dx1, Dx2 );
  1111.               Buffer = Dest->SetOffset ( 0, StartY );
  1112.  
  1113.               if (IsTexture)
  1114.                 {
  1115.                   SetUData ( u1, u2, Du1, Du2 );
  1116.                   SetVData ( v1, v2, Dv1, Dv2 );
  1117.                   SetImageBuffer ( Image->GetBuffer () );
  1118.                 } // End if
  1119.                   
  1120.               if (IsGouraud)
  1121.                 {
  1122.                   SetIntensities ( I1, I2, DI1, DI2 );
  1123.                   SetGShadeTable ( ShadeTable->GetTable() );
  1124.                 } // End if
  1125.                                 
  1126.               DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
  1127.             } // End if    
  1128.           break;
  1129.  
  1130.         case 2 :
  1131.           if (Points[High].x<=Points[Middle].x)
  1132.             {
  1133.               Left = High;
  1134.               Right = Middle;
  1135.             } // End if
  1136.           else
  1137.             {
  1138.               Left = Middle;
  1139.               Right = High;
  1140.             } // End if
  1141.  
  1142.           Dx1 = (Points[Low].x-Points[Left].x)<<16;
  1143.           Dx2 = (Points[Low].x-Points[Right].x)<<16;
  1144.  
  1145.           Dy1 = Points[Low].y-Points[Left].y+1;
  1146.           Dy2 = Points[Low].y-Points[Right].y+1;
  1147.  
  1148.           Dx1 = Dx1 / Dy1;
  1149.           Dx2 = Dx2 / Dy2;
  1150.  
  1151.           x1 = Points[Left].x <<16;
  1152.           x2 = Points[Right].x <<16;
  1153.         
  1154.           if (IsTexture)
  1155.             {
  1156.               Du1 = ((LONG)Points[Low].u-Points[Left].u)<<16;
  1157.               Du2 = ((LONG)Points[Low].u-Points[Right].u)<<16;
  1158.               Dv1 = ((LONG)Points[Low].v-Points[Left].v)<<16;
  1159.               Dv2 = ((LONG)Points[Low].v-Points[Right].v)<<16;
  1160.               
  1161.               Du1 = Du1 / Dy1;
  1162.               Du2 = Du2 / Dy2;
  1163.               Dv1 = Dv1 / Dy1;
  1164.               Dv2 = Dv2 / Dy2;
  1165.           
  1166.               u1 = (LONG)Points[Left].u <<16;
  1167.               u2 = (LONG)Points[Right].u <<16;
  1168.               v1 = (LONG)Points[Left].v <<16;
  1169.               v2 = (LONG)Points[Right].v <<16;
  1170.             } // End if  
  1171.           
  1172.           if (IsGouraud)
  1173.             {
  1174.               DI1 = ((LONG)Points[Low].Intensity-(LONG)Points[Left].Intensity)<<16;
  1175.               DI2 = ((LONG)Points[Low].Intensity-(LONG)Points[Right].Intensity)<<16;
  1176.           
  1177.               DI1 = DI1 / Dy1;
  1178.               DI2 = DI2 / Dy2;
  1179.  
  1180.               I1 = (LONG)Points[Left].Intensity << 16;
  1181.               I2 = (LONG)Points[Right].Intensity << 16;
  1182.             } // End if
  1183.  
  1184.           Length = Points[Low].y-Points[High].y+1;
  1185.           Diff = 0;
  1186.           if (Points[High].y<ViewPort.y1)
  1187.             {
  1188.               Diff = ViewPort.y1-Points[High].y;
  1189.               StartY = ViewPort.y1;
  1190.               Length -= Diff;
  1191.               x1 += Dx1*Diff;             
  1192.               x2 += Dx2*Diff;
  1193.  
  1194.               if (IsTexture)
  1195.                 {
  1196.                   u1 += Du1*Diff;
  1197.                   u2 += Du2*Diff;
  1198.                   v1 += Dv1*Diff;
  1199.                   v2 += Dv2*Diff;
  1200.                 } // End if
  1201.                   
  1202.               if (IsGouraud)
  1203.                 {
  1204.                   I1 += DI1*Diff;             
  1205.                   I2 += DI2*Diff;
  1206.                 } // End if
  1207.             } // End i
  1208.           else
  1209.             StartY = Points[High].y;
  1210.  
  1211.           if (Points[Low].y>ViewPort.y2)
  1212.             Length -= Points[Low].y - ViewPort.y2;
  1213.  
  1214.           if (Length>0)
  1215.             {  
  1216.               SetLeftRight ( x1, x2, Dx1, Dx2 );
  1217.               Buffer = Dest->SetOffset ( 0, StartY );
  1218.  
  1219.               if (IsTexture)
  1220.                 {
  1221.                   SetUData ( u1, u2, Du1, Du2 );
  1222.                   SetVData ( v1, v2, Dv1, Dv2 );
  1223.                   SetImageBuffer ( Image->GetBuffer () );
  1224.                 } // End if
  1225.                 
  1226.               if (IsGouraud)
  1227.                 {
  1228.                   SetIntensities ( I1, I2, DI1, DI2 );
  1229.                   SetGShadeTable ( ShadeTable->GetTable() );
  1230.                 } // End if
  1231.                 
  1232.               DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
  1233.             } // End if    
  1234.           break;
  1235.           
  1236.         case 3 :
  1237.           Dx1 = (Points[Middle].x-Points[High].x)<<16;
  1238.           Dx2 = (Points[Low].x-Points[High].x)<<16;
  1239.           Dx3 = (Points[Low].x-Points[Middle].x)<<16;
  1240.  
  1241.           Dy1 = Points[Middle].y-Points[High].y;
  1242.           Dy2 = Points[Low].y-Points[High].y+1;
  1243.           Dy3 = Points[Low].y-Points[Middle].y+1;
  1244.           
  1245.           Dx1 = Dx1 / Dy1;
  1246.           Dx2 = Dx2 / Dy2;
  1247.           Dx3 = Dx3 / Dy3;
  1248.           Dx4 = Dx2;
  1249.  
  1250.           x1 = Points[High].x <<16;
  1251.           x2 = Points[High].x <<16;
  1252.           x3 = Points[Middle].x << 16;
  1253.           x4 = Points[High].x << 16;
  1254.           x4 += Dy1*Dx4;
  1255.  
  1256.           if (IsTexture)
  1257.             {
  1258.               Du1 = ((LONG)Points[Middle].u-Points[High].u)<<16;
  1259.               Du2 = ((LONG)Points[Low].u-Points[High].u)<<16;
  1260.               Du3 = ((LONG)Points[Low].u-Points[Middle].u)<<16;
  1261.               Dv1 = ((LONG)Points[Middle].v-Points[High].v)<<16;
  1262.               Dv2 = ((LONG)Points[Low].v-Points[High].v)<<16;
  1263.               Dv3 = ((LONG)Points[Low].v-Points[Middle].v)<<16;
  1264.           
  1265.               Du1 = Du1 / Dy1;
  1266.               Du2 = Du2 / Dy2;
  1267.               Du3 = Du3 / Dy3;
  1268.               Du4 = Du2;
  1269.               Dv1 = Dv1 / Dy1;
  1270.               Dv2 = Dv2 / Dy2;
  1271.               Dv3 = Dv3 / Dy3;
  1272.               Dv4 = Dv2;
  1273.          
  1274.               u1 = (LONG)Points[High].u <<16;
  1275.               u2 = (LONG)Points[High].u <<16;
  1276.               u3 = (LONG)Points[Middle].u <<16;
  1277.               u4 = (LONG)Points[High].u <<16;
  1278.               u4 += Dy1*Du4;
  1279.               v1 = (LONG)Points[High].v <<16;
  1280.               v2 = (LONG)Points[High].v <<16;
  1281.               v3 = (LONG)Points[Middle].v <<16;
  1282.               v4 = (LONG)Points[High].v <<16;
  1283.               v4 += Dy1*Dv4;
  1284.             } // End if
  1285.             
  1286.           if (IsGouraud)
  1287.             {
  1288.               DI1 = ((LONG)Points[Middle].Intensity-(LONG)Points[High].Intensity)<<16;
  1289.               DI2 = ((LONG)Points[Low].Intensity-(LONG)Points[High].Intensity)<<16;
  1290.               DI3 = ((LONG)Points[Low].Intensity-(LONG)Points[Middle].Intensity)<<16;
  1291.           
  1292.               DI1 = DI1 / Dy1;
  1293.               DI2 = DI2 / Dy2;
  1294.               DI3 = DI3 / Dy3;
  1295.               DI4 = DI2;
  1296.  
  1297.               I1 = (LONG)Points[High].Intensity << 16;
  1298.               I2 = (LONG)Points[High].Intensity << 16;
  1299.               I3 = (LONG)Points[Middle].Intensity << 16;
  1300.               I4 = (LONG)Points[High].Intensity << 16;
  1301.               I4 += Dy1*DI4;
  1302.             } //  End if
  1303.  
  1304.           if (Dx1>Dx2)
  1305.             {
  1306.               Temp = Dx1;
  1307.               Dx1 = Dx2;
  1308.               Dx2 = Temp;
  1309.  
  1310.               Temp = Du1;
  1311.               Du1 = Du2;
  1312.               Du2 = Temp;
  1313.  
  1314.               Temp = Dv1;
  1315.               Dv1 = Dv2;
  1316.               Dv2 = Temp;
  1317.  
  1318.               Temp = DI1;
  1319.               DI1 = DI2;
  1320.               DI2 = Temp;
  1321.             } // End if
  1322.             
  1323.           if (Points[Middle].y>ViewPort.y1)
  1324.             {                    
  1325.               Length = Points[Middle].y-Points[High].y;
  1326.               Diff = 0;
  1327.               if (Points[High].y<ViewPort.y1)
  1328.                 {
  1329.                   Diff = ViewPort.y1-Points[High].y;
  1330.                   StartY = ViewPort.y1;
  1331.                   Length -= Diff;
  1332.                   x1 += Dx1*Diff;             
  1333.                   x2 += Dx2*Diff;
  1334.  
  1335.                   if (IsTexture)
  1336.                     {
  1337.                       u1 += Du1*Diff;             
  1338.                       u2 += Du2*Diff;
  1339.                       v1 += Dv1*Diff;             
  1340.                       v2 += Dv2*Diff;
  1341.                     } // End if
  1342.  
  1343.                   if (IsGouraud)
  1344.                     {
  1345.                       I1 += DI1*Diff;             
  1346.                       I2 += DI2*Diff;
  1347.                     } // End if
  1348.                 } // End if
  1349.               else
  1350.                 StartY = Points[High].y;
  1351.  
  1352.               if (Points[Middle].y-1>ViewPort.y2)
  1353.                 Length -= (Points[Middle].y-1) - ViewPort.y2;
  1354.             
  1355.               if (Length>0)
  1356.                 {  
  1357.                   SetLeftRight ( x1, x2, Dx1, Dx2 );
  1358.                   Buffer = Dest->SetOffset ( 0, StartY );
  1359.  
  1360.                   if (IsTexture)
  1361.                     {
  1362.                       SetUData ( u1, u2, Du1, Du2 );
  1363.                       SetVData ( v1, v2, Dv1, Dv2 );
  1364.                       SetImageBuffer ( Image->GetBuffer () );
  1365.                     } // End if
  1366.                       
  1367.                   if (IsGouraud)
  1368.                     {
  1369.                       SetIntensities ( I1, I2, DI1, DI2 );
  1370.                       SetGShadeTable ( ShadeTable->GetTable() );
  1371.                     } // End if  
  1372.                   DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
  1373.                 } // End if    
  1374.             } // End if
  1375.  
  1376.           if (Points[Middle].y<=ViewPort.y2)
  1377.             {              
  1378.               Length = Points[Low].y-Points[Middle].y+1;
  1379.               Diff = 0;
  1380.               if (Points[Middle].y<ViewPort.y1)
  1381.                 {
  1382.                   Diff = ViewPort.y1-Points[Middle].y;
  1383.                   StartY = ViewPort.y1;
  1384.                   Length -= Diff;
  1385.                   x3 += Dx3*Diff;             
  1386.                   x4 += Dx4*Diff;
  1387.  
  1388.                   if (IsTexture)
  1389.                     {
  1390.                       u3 += Du3*Diff;             
  1391.                       u4 += Du4*Diff;
  1392.                       v3 += Dv3*Diff;             
  1393.                       v4 += Dv4*Diff;
  1394.                     } // End if
  1395.  
  1396.                   if (IsGouraud)
  1397.                     {
  1398.                       I3 += DI3*Diff;             
  1399.                       I4 += DI4*Diff;
  1400.                     } // End if
  1401.                 } // End if
  1402.               else
  1403.                 StartY = Points[Middle].y;
  1404.  
  1405.               if (Points[Low].y>ViewPort.y2)
  1406.                 Length -= Points[Low].y - ViewPort.y2;
  1407.  
  1408.               if (x3>x4)
  1409.                 {
  1410.                   Temp = x3;
  1411.                   x3 = x4;
  1412.                   x4 = Temp;
  1413.  
  1414.                   Temp = Dx3;
  1415.                   Dx3 = Dx4;
  1416.                   Dx4 = Temp;
  1417.  
  1418.                   Temp = u3;
  1419.                   u3 = u4;
  1420.                   u4 = Temp;
  1421.  
  1422.                   Temp = v3;
  1423.                   v3 = v4;
  1424.                   v4 = Temp;
  1425.  
  1426.                   Temp = Du3;
  1427.                   Du3 = Du4;
  1428.                   Du4 = Temp;
  1429.  
  1430.                   Temp = Dv3;
  1431.                   Dv3 = Dv4;
  1432.                   Dv4 = Temp;
  1433.  
  1434.                   Temp = I3;
  1435.                   I3 = I4;
  1436.                   I4 = Temp;
  1437.  
  1438.                   Temp = DI3;
  1439.                   DI3 = DI4;
  1440.                   DI4 = Temp;
  1441.                 } // End if
  1442.                 
  1443.               if (Length>0)
  1444.                 {  
  1445.                   SetLeftRight ( x3, x4, Dx3, Dx4 );
  1446.                   Buffer = Dest->SetOffset ( 0, StartY );
  1447.  
  1448.                   if (IsTexture)
  1449.                     {
  1450.                       SetUData ( u3, u4, Du3, Du4 );
  1451.                       SetVData ( v3, v4, Dv3, Dv4 );
  1452.                       SetImageBuffer ( Image->GetBuffer () );
  1453.                     } // End if
  1454.                     
  1455.                   if (IsGouraud)
  1456.                     {
  1457.                       SetIntensities ( I3, I4, DI3, DI4 );
  1458.                     } // End if  
  1459.                   DrawMesh ( Buffer, Dest->GetRowInc(), Color, Length );
  1460.                 } // End if    
  1461.             } // End if                
  1462.           break;    
  1463.       } // End case                  
  1464.   } // End of DrawTriMesh for G3DENGINE
  1465.  
  1466. VOID G3DENGINE::UpdateWorld ()
  1467.   {
  1468.     InitMatrix ( MasterMatrix );
  1469.  
  1470.     POINT3D Position;
  1471.     POINT3D Angle;
  1472.     
  1473.     Position = Camera->GetPosition ();
  1474.     Angle = Camera->GetAngle ();
  1475.     
  1476.     Translate ( MasterMatrix, -Position.x, -Position.y, -Position.z );
  1477.     Rotate ( MasterMatrix, -Angle.x, -Angle.y, -Angle.z );
  1478.     
  1479.     Transform ();  
  1480.   } // End of UpdateWorld for G3DENGINE
  1481.  
  1482. BOOLEAN G3DENGINE::CreateDatabase ( STRING FileName, double x, double y, double z  )
  1483.   {
  1484.     G3DWORLD *NewWorld;
  1485.     INT i;
  1486.     
  1487.     NewWorld = new G3DWORLD ();
  1488.     NewWorld->CreateObjects ( 1 );
  1489.     NewWorld->CreateTextures ( 1 );
  1490.     
  1491.     NewWorld->CreateLights ( 1 );
  1492.     G3DLIGHT **LightList = NewWorld->GetLightList ();
  1493.     LightList[0]->SetPosition ( 0, 0, 0 );
  1494.     LightList[0]->SetDirection ( 1, 0, 1 );
  1495.     
  1496.     IMAGE **Images;
  1497.     Images = NewWorld->GetTextureList ();
  1498.     Grafix.LoadImage ( "texture.pcx", Images[0], NULL );
  1499.  
  1500.     G3DOBJECT **Object;
  1501.     Object = NewWorld->GetObjectList ();
  1502.  
  1503.     Object[0]->SetPosition ( x, y, z );
  1504.     Object[0]->SetLightSource ( 0 );
  1505.  
  1506.     LINKEDLIST<POINT3D> *ListPoint = new LINKEDLIST<POINT3D> ();
  1507.     LINKEDLIST<MESH3D> *ListMesh = new LINKEDLIST<MESH3D> ();
  1508.     
  1509.     if (LoadASC ( FileName, ListPoint, ListMesh )==FAILURE)
  1510.       return FAILURE;
  1511.     
  1512.     Object[0]->CreatePoints ( ListPoint->GetNumObjects() );
  1513.     Object[0]->CreateMeshes ( ListMesh->GetNumObjects() );
  1514.     
  1515.     POINT3D *Points;
  1516.     MESH3D  *Mesh;
  1517.     LISTOBJECT<POINT3D> *PointPtr;
  1518.     LISTOBJECT<MESH3D> *MeshPtr;
  1519.     
  1520.     Points = Object[0]->GetLocal3DList ();
  1521.     Mesh = Object[0]->GetMeshList ();
  1522.  
  1523.     PointPtr = ListPoint->GetHead ();
  1524.     for (i=0;i<ListPoint->GetNumObjects();i++)
  1525.       {
  1526.         Points[i] = PointPtr->Data;
  1527.         PointPtr = PointPtr->NextObject;  
  1528.       } // End for
  1529.       
  1530.     MeshPtr = ListMesh->GetHead ();
  1531.     for (i=0;i<ListMesh->GetNumObjects();i++)
  1532.       {
  1533.         Mesh[i].Points[0] = MeshPtr->Data.Points[0];
  1534.         Mesh[i].Points[1] = MeshPtr->Data.Points[1];
  1535.         Mesh[i].Points[2] = MeshPtr->Data.Points[2];
  1536.         Mesh[i].Flags = MESH_TEXTURE | MESH_GOURAUD | MESH_REVERSED;
  1537.         Mesh[i].Surface = 255;
  1538.         Mesh[i].Texture = 0;
  1539.         Mesh[i].TexPoints[0].u = 255;
  1540.         Mesh[i].TexPoints[0].v = 0;
  1541.         Mesh[i].TexPoints[1].u = 0;
  1542.         Mesh[i].TexPoints[1].v = 255;
  1543.         Mesh[i].TexPoints[2].u = 255;
  1544.         Mesh[i].TexPoints[2].v = 255;
  1545.         MeshPtr = MeshPtr->NextObject;  
  1546.       } // End for
  1547.  
  1548.     delete ListPoint;
  1549.     delete ListMesh;
  1550.     
  1551.     if (World!=NULL)
  1552.       delete World;
  1553.     World = NULL;  
  1554.     SetWorld ( NewWorld );
  1555.     return SUCCESS;
  1556.   } // End of CreateDatabase for G3DENGINE
  1557.  
  1558. VOID G3DENGINE::SetViewData ( LONG NewCenterX, LONG NewCenterY, LONG NewDistance )
  1559.   {
  1560.     CenterX = NewCenterX;  
  1561.     CenterY = NewCenterY;  
  1562.     Distance = NewDistance;  
  1563.   } // End of SetViewData for G3DENGINE
  1564.  
  1565. VOID G3DENGINE::ZIntersect ( CLIPPOINT3D *In, CLIPPOINT3D *Out, CLIPPOINT3D *Intersect, LONG Flags )
  1566.   {
  1567.     double Ratio;
  1568.  
  1569.     Ratio = (double)(MIN_Z_DISTANCE-Out->z)/(double)(In->z-Out->z);
  1570.     
  1571.     Intersect->x = (double)(In->x-Out->x)*Ratio + Out->x;
  1572.     Intersect->y = (double)(In->y-Out->y)*Ratio + Out->y;
  1573.     Intersect->z = MIN_Z_DISTANCE;
  1574.     
  1575.     if (Flags&MESH_GOURAUD)
  1576.       {
  1577.         Intersect->Intensity = (double)(In->Intensity-Out->Intensity)*Ratio +
  1578.                                 Out->Intensity;  
  1579.       } // End if
  1580.       
  1581.     if (Flags&MESH_TEXTURE)
  1582.       {
  1583.         Intersect->u = (double)(In->u-Out->u)*Ratio + Out->u;  
  1584.         Intersect->v = (double)(In->v-Out->v)*Ratio + Out->v;  
  1585.       } // End if
  1586.   } // End of ZIntersect for G3DENGINE
  1587.  
  1588. INT G3DENGINE::ZClip ( CLIPPOINT3D *SrcPoints, CLIPPOINT3D *PolyPoints, LONG Flags )
  1589.   {
  1590.     CLIPPOINT3D P1,P2,I;
  1591.     INT i;
  1592.     INT NumPts;
  1593.  
  1594.     P1 = SrcPoints[2];    
  1595.     NumPts = 0;
  1596.     
  1597.     for (i=0;i<3;i++)
  1598.       {
  1599.         P2 = SrcPoints[i];  
  1600.         if (P2.z>=MIN_Z_DISTANCE)
  1601.           {
  1602.             if (P1.z<MIN_Z_DISTANCE)
  1603.               {
  1604.                 ZIntersect ( &P2, &P1, &I, Flags );
  1605.                 PolyPoints[NumPts++] = I;
  1606.                 PolyPoints[NumPts++] = P2;
  1607.               } // End if
  1608.             else
  1609.               {
  1610.                 PolyPoints[NumPts++] = P2;
  1611.               } // End else  
  1612.           } // End if
  1613.         else
  1614.           {
  1615.             if (P1.z>=MIN_Z_DISTANCE)
  1616.               {
  1617.                 ZIntersect ( &P1, &P2, &I, Flags );
  1618.                 PolyPoints[NumPts++] = I;
  1619.               } // End if                
  1620.           } // End else
  1621.         P1 = P2;  
  1622.       } // End for
  1623.     return NumPts;  
  1624.   } // End of ZClip for G3DENGINE
  1625.  
  1626. VOID G3DENGINE::DisplayMesh ( G3DOBJECT *Object, MESH3D *Mesh )
  1627.   {
  1628.     POINT2D *Points;
  1629.     LONG *IntensityList;
  1630.     LONG *List;
  1631.     
  1632.     Points = Object->GetScr2DList ();
  1633.     List = Mesh->Points;
  1634.  
  1635.     Grafix.FGColor = Mesh->Surface;
  1636.  
  1637.     DRAWPOINT2D DrawPoints[3];
  1638.     SHORT Flags = Mesh->Flags;
  1639.  
  1640.     if (SurfaceMethod==SURFACE_SOLID)
  1641.       {
  1642.         Flags &= ~MESH_TEXTURE;
  1643.         Flags |= MESH_SOLID;
  1644.       } // End if        
  1645.     else if (SurfaceMethod<SURFACE_SOLID)
  1646.       {
  1647.         Flags &= ~MESH_TEXTURE;
  1648.         Flags &= ~MESH_SOLID;
  1649.       } // End else if  
  1650.     
  1651.     if (ShadeMethod==SHADE_FLAT)
  1652.       {
  1653.         Flags &= ~MESH_GOURAUD;
  1654.         Flags |= MESH_FLAT;
  1655.       } // End if      
  1656.     else if (ShadeMethod<SHADE_FLAT)
  1657.       {
  1658.         Flags &= ~MESH_GOURAUD;
  1659.         Flags &= ~MESH_FLAT;
  1660.       } // End else if 
  1661.  
  1662.     BYTE Color;
  1663.     BYTE *Table;
  1664.     LONG Intensity;
  1665.     IMAGE *Texture=NULL;
  1666.     
  1667.     if (Mesh->MinZ>=MIN_Z_DISTANCE)
  1668.       {    
  1669.         if (((Flags&MESH_SOLID)==0)&&     // Wireframe
  1670.               ((Flags&MESH_TEXTURE)==0))
  1671.           {
  1672.             Grafix.DrawLine ( Dest, Points[List[0]].x+CenterX, Points[List[0]].y+CenterY,
  1673.                               Points[List[1]].x+CenterX, Points[List[1]].y+CenterY );
  1674.             Grafix.DrawLine ( Dest, Points[List[1]].x+CenterX, Points[List[1]].y+CenterY,
  1675.                               Points[List[2]].x+CenterX, Points[List[2]].y+CenterY );
  1676.             Grafix.DrawLine ( Dest, Points[List[2]].x+CenterX, Points[List[2]].y+CenterY,
  1677.                               Points[List[0]].x+CenterX, Points[List[0]].y+CenterY );
  1678.           } // End if                          
  1679.         else if (Flags&MESH_SOLID)     // Solid Color
  1680.           {  
  1681.             DrawPoints[0].x = Points[List[0]].x + CenterX;  
  1682.             DrawPoints[0].y = Points[List[0]].y + CenterY;  
  1683.             DrawPoints[1].x = Points[List[1]].x + CenterX;  
  1684.             DrawPoints[1].y = Points[List[1]].y + CenterY;  
  1685.             DrawPoints[2].x = Points[List[2]].x + CenterX;  
  1686.             DrawPoints[2].y = Points[List[2]].y + CenterY;  
  1687.             if (Flags&MESH_FLAT)
  1688.               {
  1689.                 if (ShadeTable==NULL)
  1690.                   Color = Mesh->Surface;
  1691.                 else
  1692.                   {
  1693.                     Table = ShadeTable->GetTable();
  1694.                     Intensity = World->GetMeshIntensity ( Object, Mesh );
  1695.                     Color = Table[(Intensity&0xFF00)+Mesh->Surface];
  1696.                   } // End else            
  1697.               } // End if
  1698.             else if (Flags&MESH_GOURAUD)
  1699.               {
  1700.                 IntensityList = Object->GetIntensityList ();
  1701.                 DrawPoints[0].Intensity = IntensityList[List[0]];
  1702.                 DrawPoints[1].Intensity = IntensityList[List[1]];
  1703.                 DrawPoints[2].Intensity = IntensityList[List[2]];
  1704.                 Color = Mesh->Surface;
  1705.               } // End if
  1706.             else
  1707.               {
  1708.                 Color = Mesh->Surface;
  1709.               } // End else            
  1710.             DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1711.           } // End else if
  1712.         else if (Flags&MESH_TEXTURE)
  1713.           {
  1714.             if (TextureList==NULL)
  1715.               return;
  1716.             Texture = TextureList[Mesh->Texture];
  1717.             DrawPoints[0].x = Points[List[0]].x + CenterX;  
  1718.             DrawPoints[0].y = Points[List[0]].y + CenterY;  
  1719.             DrawPoints[1].x = Points[List[1]].x + CenterX;  
  1720.             DrawPoints[1].y = Points[List[1]].y + CenterY;  
  1721.             DrawPoints[2].x = Points[List[2]].x + CenterX;  
  1722.             DrawPoints[2].y = Points[List[2]].y + CenterY;
  1723.             DrawPoints[0].u = Mesh->TexPoints[0].u;
  1724.             DrawPoints[0].v = Mesh->TexPoints[0].v;
  1725.             DrawPoints[1].u = Mesh->TexPoints[1].u;
  1726.             DrawPoints[1].v = Mesh->TexPoints[1].v;
  1727.             DrawPoints[2].u = Mesh->TexPoints[2].u;
  1728.             DrawPoints[2].v = Mesh->TexPoints[2].v;
  1729.             if (Flags&MESH_FLAT)
  1730.               {
  1731.                 Intensity = World->GetMeshIntensity ( Object, Mesh );
  1732.               } // End if
  1733.             else if (Flags&MESH_GOURAUD)
  1734.               {
  1735.                 IntensityList = Object->GetIntensityList ();
  1736.                 DrawPoints[0].Intensity = IntensityList[List[0]];
  1737.                 DrawPoints[1].Intensity = IntensityList[List[1]];
  1738.                 DrawPoints[2].Intensity = IntensityList[List[2]];
  1739.               } // End if
  1740.             DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1741.           } // End else if
  1742.       } // End if
  1743.     else
  1744.       {
  1745.         CLIPPOINT3D Src[3];
  1746.         CLIPPOINT3D Clipped[4];
  1747.         POINT3D *WPoints;
  1748.         INT NumPts;
  1749.  
  1750.         WPoints = Object->GetCamera3DList ();
  1751.         
  1752.         Src[0].x=WPoints[List[0]].x; Src[0].y=WPoints[List[0]].y; Src[0].z=WPoints[List[0]].z;        
  1753.         Src[1].x=WPoints[List[1]].x; Src[1].y=WPoints[List[1]].y; Src[1].z=WPoints[List[1]].z;        
  1754.         Src[2].x=WPoints[List[2]].x; Src[2].y=WPoints[List[2]].y; Src[2].z=WPoints[List[2]].z;
  1755.  
  1756.         if (Flags&MESH_GOURAUD)
  1757.           {
  1758.             IntensityList = Object->GetIntensityList ();
  1759.             Src[0].Intensity = IntensityList[List[0]];
  1760.             Src[1].Intensity = IntensityList[List[1]];
  1761.             Src[2].Intensity = IntensityList[List[2]];            
  1762.           } // End if
  1763.  
  1764.         if (Flags&MESH_TEXTURE)
  1765.           {
  1766.             Src[0].u=Mesh->TexPoints[0].u; Src[0].v=Mesh->TexPoints[0].v;  
  1767.             Src[1].u=Mesh->TexPoints[1].u; Src[1].v=Mesh->TexPoints[1].v;  
  1768.             Src[2].u=Mesh->TexPoints[2].u; Src[2].v=Mesh->TexPoints[2].v;  
  1769.           } // End if
  1770.             
  1771.         NumPts = ZClip ( Src, Clipped, Flags );
  1772.         LONG x1,y1,x2,y2,x3,y3,x4,y4;
  1773.  
  1774.         x1 = Clipped[0].x*Distance/Clipped[0].z + CenterX;
  1775.         y1 = -Clipped[0].y*Distance/Clipped[0].z + CenterY;
  1776.         x2 = Clipped[1].x*Distance/Clipped[1].z + CenterX;
  1777.         y2 = -Clipped[1].y*Distance/Clipped[1].z + CenterY;
  1778.         x3 = Clipped[2].x*Distance/Clipped[2].z + CenterX;
  1779.         y3 = -Clipped[2].y*Distance/Clipped[2].z + CenterY;
  1780.         
  1781.         if (NumPts==4)
  1782.           {
  1783.             x4 = Clipped[3].x*Distance/Clipped[3].z + CenterX;
  1784.             y4 = -Clipped[3].y*Distance/Clipped[3].z + CenterY;
  1785.           } // End if
  1786.           
  1787.         if (((Flags&MESH_SOLID)==0)&&     // Wireframe
  1788.               ((Flags&MESH_TEXTURE)==0))
  1789.           {
  1790.             if (NumPts==3)
  1791.               {
  1792.                 Grafix.DrawLine ( Dest, x1, y1, x2, y2 );
  1793.                 Grafix.DrawLine ( Dest, x2, y2, x3, y3 );
  1794.                 Grafix.DrawLine ( Dest, x3, y3, x1, y1 );
  1795.               } // End if
  1796.             else
  1797.               {
  1798.                 Grafix.DrawLine ( Dest, x1, y1, x2, y2 );
  1799.                 Grafix.DrawLine ( Dest, x2, y2, x3, y3 );
  1800.                 Grafix.DrawLine ( Dest, x3, y3, x4, y4 );
  1801.                 Grafix.DrawLine ( Dest, x4, y4, x1, y1 );
  1802.               } // End else  
  1803.           } // End if                          
  1804.         else if (Flags&MESH_SOLID)     // Solid Color
  1805.           {  
  1806.             DrawPoints[0].x = x1;  
  1807.             DrawPoints[0].y = y1;  
  1808.             DrawPoints[1].x = x2;  
  1809.             DrawPoints[1].y = y2;  
  1810.             DrawPoints[2].x = x3;  
  1811.             DrawPoints[2].y = y3;  
  1812.             if (Flags&MESH_FLAT)
  1813.               {
  1814.                 if (ShadeTable==NULL)
  1815.                   Color = Mesh->Surface;
  1816.                 else
  1817.                   {
  1818.                     Table = ShadeTable->GetTable();
  1819.                     Intensity = World->GetMeshIntensity ( Object, Mesh );
  1820.                     Color = Table[(Intensity&0xFF00)+Mesh->Surface];
  1821.                   } // End else            
  1822.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1823.                 if (NumPts==4)
  1824.                   {
  1825.                     DrawPoints[1].x = x3;  
  1826.                     DrawPoints[1].y = y3;  
  1827.                     DrawPoints[2].x = x4;  
  1828.                     DrawPoints[2].y = y4;  
  1829.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1830.                   } // End if
  1831.               } // End if
  1832.             else if (Flags&MESH_GOURAUD)
  1833.               {
  1834.                 DrawPoints[0].Intensity = Clipped[0].Intensity;  
  1835.                 DrawPoints[1].Intensity = Clipped[1].Intensity;  
  1836.                 DrawPoints[2].Intensity = Clipped[2].Intensity;
  1837.                 
  1838.                 Color = Mesh->Surface;
  1839.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1840.                 if (NumPts==4)
  1841.                   {
  1842.                     DrawPoints[1].x = x3;  
  1843.                     DrawPoints[1].y = y3;  
  1844.                     DrawPoints[2].x = x4;  
  1845.                     DrawPoints[2].y = y4;  
  1846.                     DrawPoints[1].Intensity = Clipped[2].Intensity;  
  1847.                     DrawPoints[2].Intensity = Clipped[3].Intensity;
  1848.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1849.                   } // End if
  1850.               } // End if
  1851.             else
  1852.               {
  1853.                 Color = Mesh->Surface;
  1854.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1855.                 if (NumPts==4)
  1856.                   {
  1857.                     DrawPoints[1].x = x3;  
  1858.                     DrawPoints[1].y = y3;  
  1859.                     DrawPoints[2].x = x4;  
  1860.                     DrawPoints[2].y = y4;  
  1861.                     DrawPoints[1].Intensity = Clipped[2].Intensity;  
  1862.                     DrawPoints[2].Intensity = Clipped[3].Intensity;
  1863.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1864.                   } // End if
  1865.               } // End else            
  1866.           } // End else if
  1867.         else if (Flags&MESH_TEXTURE)     // Texture 
  1868.           {  
  1869.             if (TextureList==NULL)
  1870.               return;
  1871.             Texture = TextureList[Mesh->Texture];
  1872.  
  1873.             DrawPoints[0].x = x1;  
  1874.             DrawPoints[0].y = y1;  
  1875.             DrawPoints[1].x = x2;  
  1876.             DrawPoints[1].y = y2;  
  1877.             DrawPoints[2].x = x3;  
  1878.             DrawPoints[2].y = y3;  
  1879.             DrawPoints[0].u = Clipped[0].u;
  1880.             DrawPoints[0].v = Clipped[0].v;
  1881.             DrawPoints[1].u = Clipped[1].u;
  1882.             DrawPoints[1].v = Clipped[1].v;
  1883.             DrawPoints[2].u = Clipped[2].u;
  1884.             DrawPoints[2].v = Clipped[2].v;
  1885.             if (Flags&MESH_FLAT)
  1886.               {
  1887.                 Intensity = World->GetMeshIntensity ( Object, Mesh );
  1888.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1889.                 if (NumPts==4)
  1890.                   {
  1891.                     DrawPoints[1].x = x3;  
  1892.                     DrawPoints[1].y = y3;  
  1893.                     DrawPoints[2].x = x4;  
  1894.                     DrawPoints[2].y = y4;  
  1895.                     DrawPoints[1].u = Clipped[3].u;
  1896.                     DrawPoints[1].v = Clipped[3].v;
  1897.                     DrawPoints[2].u = Clipped[4].u;
  1898.                     DrawPoints[2].v = Clipped[4].v;
  1899.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1900.                   } // End if
  1901.               } // End if
  1902.             else if (Flags&MESH_GOURAUD)
  1903.               {
  1904.                 DrawPoints[0].Intensity = Clipped[0].Intensity;  
  1905.                 DrawPoints[1].Intensity = Clipped[1].Intensity;  
  1906.                 DrawPoints[2].Intensity = Clipped[2].Intensity;
  1907.                 
  1908.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
  1909.                 
  1910.                 if (NumPts==4)
  1911.                   {
  1912.                     DrawPoints[1].x = x3;  
  1913.                     DrawPoints[1].y = y3;  
  1914.                     DrawPoints[2].x = x4;  
  1915.                     DrawPoints[2].y = y4;  
  1916.                     DrawPoints[1].u = Clipped[3].u;
  1917.                     DrawPoints[1].v = Clipped[3].v;
  1918.                     DrawPoints[2].u = Clipped[4].u;
  1919.                     DrawPoints[2].v = Clipped[4].v;
  1920.                     DrawPoints[1].Intensity = Clipped[2].Intensity;  
  1921.                     DrawPoints[2].Intensity = Clipped[3].Intensity;
  1922.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
  1923.                   } // End if
  1924.               } // End if
  1925.             else
  1926.               {
  1927.                 DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags );
  1928.                 if (NumPts==4)
  1929.                   {
  1930.                     DrawPoints[1].x = x3;  
  1931.                     DrawPoints[1].y = y3;  
  1932.                     DrawPoints[2].x = x4;  
  1933.                     DrawPoints[2].y = y4;  
  1934.                     DrawPoints[1].u = Clipped[3].u;
  1935.                     DrawPoints[1].v = Clipped[3].v;
  1936.                     DrawPoints[2].u = Clipped[4].u;
  1937.                     DrawPoints[2].v = Clipped[4].v;
  1938.                     DrawTriMesh ( Dest, DrawPoints, Color, Texture, Intensity, Flags ); 
  1939.                   } // End if
  1940.               } // End else            
  1941.           } // End else if
  1942.       } // End else      
  1943.   } // End of DisplayMesh for G3DENGINE
  1944.  
  1945. VOID G3DENGINE::SetCamera ( double x, double y, double z,
  1946.                             double xa, double ya, double za )
  1947.   {
  1948.     Camera->SetPosition ( x, y, z );  
  1949.     Camera->SetAngle ( xa, ya, za );  
  1950.   } // End of SetCamera for G3DENGINE
  1951.                             
  1952. VOID G3DENGINE::MoveCamera ( double x, double y, double z,
  1953.                               double xa, double ya, double za )
  1954.   {
  1955.     Camera->MovePosition ( x, y, z );  
  1956.     Camera->MoveAngle ( xa, ya, za );  
  1957.   } // End of MoveCamera for G3DENGINE
  1958.                               
  1959. VOID G3DENGINE::MoveObject ( LONG Index, double x, double y, double z,
  1960.                               double xa, double ya, double za )
  1961.   {
  1962.     if (World==NULL)
  1963.       return;
  1964.     if ((Index<0)||(Index>=World->GetNumObjects()))
  1965.       return;
  1966.       
  1967.     G3DOBJECT **ObjectList;
  1968.     
  1969.     ObjectList = World->GetObjectList ();
  1970.     ObjectList[Index]->Move ( x, y, z, xa, ya, za );
  1971.   } // End of MoveObject for G3DENGINE                              
  1972.  
  1973. INT CompareMesh ( const void *ptr1, const void *ptr2 )
  1974.   {
  1975.     G3DOBJECT *Object1,*Object2;
  1976.     MESH3D *Mesh1,*Mesh2;
  1977.  
  1978.     Object1 = ((MESHNODE*)ptr1)->Object;
  1979.     Object2 = ((MESHNODE*)ptr2)->Object;
  1980.     Mesh1 = ((MESHNODE*)ptr1)->Mesh;
  1981.     Mesh2 = ((MESHNODE*)ptr2)->Mesh;
  1982.     /*
  1983.     if (Mesh1->MinZ>Mesh2->MaxZ)
  1984.       return -1;
  1985.     else if (Mesh1->MaxZ<Mesh2->MinZ)
  1986.       return 1;
  1987.       
  1988.     if (Mesh1->MinZ+Mesh1->MaxZ<Mesh2->MinZ+Mesh2->MaxZ)
  1989.       return 1;
  1990.     else if (Mesh2->MinZ<Mesh1->MinZ)
  1991.       return -1;*/
  1992.     if (Mesh1->MaxZ > Mesh2->MaxZ)
  1993.       return -1;
  1994.     else if (Mesh1->MaxZ < Mesh2->MaxZ)
  1995.       return 1;
  1996.  
  1997.     return 0;    
  1998.   } // End of CompareMesh
  1999.                    
  2000. VOID G3DENGINE::SortMesh ()
  2001.   {
  2002.     qsort ( VisibleMeshes, NumVisibleMeshes, sizeof(MESHNODE), CompareMesh );  
  2003.   } // End of SortMesh for G3DENGINE
  2004.  
  2005. VOID G3DENGINE::AddVisibleMesh ( G3DOBJECT *Object, MESH3D *Mesh )
  2006.   {
  2007.     VisibleMeshes[NumVisibleMeshes].Object = Object;  
  2008.     VisibleMeshes[NumVisibleMeshes].Mesh = Mesh;
  2009.     NumVisibleMeshes++;
  2010.   } // End of AddVisibleMesh
  2011.  
  2012. VOID G3DENGINE::SetShadeTable ( SHADETABLE *Table )
  2013.   {
  2014.     ShadeTable = Table;
  2015.     NumShadeLevels = ShadeTable->GetNumDarkLevels () + 1 +
  2016.                        ShadeTable->GetNumLightLevels ();
  2017.     MaxShadeNumber = NumShadeLevels*256;                   
  2018.   } // End of SetShadeTable for G3DENGINE
  2019.  
  2020. INT G3DENGINE::ReadToken ( FILEHANDLE f, STRING String  )
  2021.   {
  2022.     return fscanf ( f, "%s", String );  
  2023.   } // End of ReadToken for G3DENGINE
  2024.  
  2025. INT G3DENGINE::GoToToken ( FILEHANDLE f, STRING String )
  2026.   {
  2027.     BOOLEAN Found=FALSE;
  2028.     CHAR Str[128];
  2029.  
  2030.     while (!Found)
  2031.       {
  2032.         if (ReadToken ( f, Str  )==EOF)
  2033.           return EOF;
  2034.         if (strcmp(String,Str)==0)
  2035.           Found = TRUE;
  2036.       } // End while
  2037.     return 0;  
  2038.   } // End of GoToToken for G3DENGINE
  2039.  
  2040. INT G3DENGINE::GetNumber ( FILEHANDLE f, double *Number )
  2041.   {
  2042.     CHAR Str[128];
  2043.     INT Result;
  2044.  
  2045.     Result = fscanf ( f, "%s", Str );
  2046.     *Number = atof ( Str );
  2047.     return Result;
  2048.   } // End of GetNumber for G3DENGINE
  2049.  
  2050. INT G3DENGINE::GetInt ( FILEHANDLE f, LONG *Number )
  2051.   {
  2052.     return fscanf ( f, "%d", Number );  
  2053.   } // End of GetInt for G3DENGINE
  2054.  
  2055. BOOLEAN G3DENGINE::LoadASC ( STRING FileName,
  2056.                              LINKEDLIST<POINT3D> *ListPoint,
  2057.                              LINKEDLIST<MESH3D> *ListMesh )
  2058.   {
  2059.     FILEHANDLE f;
  2060.  
  2061.     f = File.Open ( FileName, OPEN_READ | OPEN_BINARY );
  2062.  
  2063.     if (f==NULL)
  2064.       return FAILURE;
  2065.  
  2066.     BOOLEAN Done; 
  2067.     
  2068.     Done = FALSE;
  2069.  
  2070.     double x,y,z;
  2071.     LONG NumVertex,NumFaces;
  2072.     POINT3D Point;
  2073.     MESH3D  Mesh;    
  2074.     LONG P1,P2,P3;
  2075.     LONG LastVertex=0;
  2076.     
  2077.     while (!Done)
  2078.       {
  2079.         if (GoToToken( f,"Vertices:" )==EOF)
  2080.           Done = TRUE;
  2081.         else
  2082.           {
  2083.             GetInt ( f, &NumVertex );
  2084.             GoToToken( f,"Faces:" );
  2085.             GetInt ( f, &NumFaces );
  2086.             
  2087.             GoToToken ( f,"Vertex" );
  2088.             GoToToken ( f, "list:" );
  2089.             LONG i;
  2090.  
  2091.             for (i=0;i<(LONG)NumVertex;i++)
  2092.               {
  2093.                 CHAR NumStr[128];
  2094.                 GoToToken( f,"Vertex" );
  2095.  
  2096.                 sprintf ( NumStr, "%d:", i );
  2097.  
  2098.                 GoToToken ( f, NumStr );
  2099.  
  2100.                 ReadToken ( f, NumStr );
  2101.                 if (strlen(NumStr)>2)
  2102.                   x = atof ( NumStr+2 );
  2103.                 else
  2104.                   GetNumber ( f, &x );
  2105.  
  2106.                 ReadToken ( f, NumStr );
  2107.                 if (strlen(NumStr)>2)
  2108.                   y = atof ( NumStr+2 );
  2109.                 else
  2110.                   GetNumber ( f, &y );
  2111.  
  2112.                 ReadToken ( f, NumStr );
  2113.                 if (strlen(NumStr)>2)
  2114.                   z = atof ( NumStr+2 );
  2115.                 else
  2116.                   GetNumber ( f, &z );
  2117.  
  2118.                 Point.x = x;
  2119.                 Point.y = y;
  2120.                 Point.z = z;
  2121.  
  2122.                 ListPoint->AddObject ( Point );
  2123.               } // End for
  2124.               
  2125.             GoToToken( f,"Face" );
  2126.             GoToToken ( f, "list:" );
  2127.             
  2128.             for (i=0;i<(LONG)NumFaces;i++)
  2129.               {
  2130.                 GoToToken( f,"Face" );
  2131.                 CHAR Str[128];
  2132.                 sprintf ( Str, "%d:", i );
  2133.                 GoToToken ( f, Str );
  2134.  
  2135.                 ReadToken ( f, Str );
  2136.                 P1 = atoi ( Str+2 );
  2137.  
  2138.                 ReadToken ( f, Str );
  2139.                 P2 = atoi ( Str+2 );
  2140.  
  2141.                 ReadToken ( f, Str );
  2142.                 P3 = atoi ( Str+2 );
  2143.  
  2144.                 Mesh.Points[0] = (LONG)P1+LastVertex;
  2145.                 Mesh.Points[1] = (LONG)P2+LastVertex;
  2146.                 Mesh.Points[2] = (LONG)P3+LastVertex;
  2147.                 
  2148.                 ListMesh->AddObject ( Mesh );
  2149.               } // End for              
  2150.           } // End else    
  2151.         LastVertex = NumVertex;
  2152.         Done = TRUE;
  2153.       } // End while
  2154.     
  2155.     File.Close ( f );
  2156.     return SUCCESS;  
  2157.   } // End of LoadASC for G3DENGINE
  2158.  
  2159. VOID G3DENGINE::SetShadeMethod ( LONG Shade )
  2160.   {
  2161.     ShadeMethod = Shade;  
  2162.   } // End of SetShadeMethod for G3DENGINE
  2163.  
  2164. VOID G3DENGINE::SetSurfaceMethod ( LONG Surface )
  2165.   {
  2166.     SurfaceMethod = Surface;  
  2167.   } // End of SetSurfaceMethod for G3DENGINE
  2168.  
  2169. VOID G3DENGINE::ShowView ( IMAGE *Image )
  2170.   {
  2171.     if (World==NULL)
  2172.       return;
  2173.         
  2174.     Dest = Image;
  2175.     
  2176.     UpdateWorld ();
  2177.  
  2178.     LONG i,j;
  2179.     LONG NumObjects,NumMeshes;
  2180.     G3DOBJECT **ObjectList;
  2181.     G3DLIGHT **LightList;
  2182.  
  2183.     NumObjects = World->GetNumObjects ();
  2184.     ObjectList = World->GetObjectList ();
  2185.  
  2186.     NumVisibleMeshes = 0;
  2187.     for (i=0;i<NumObjects;i++)
  2188.       {
  2189.         if (ObjectList[i]->MaxZ>MIN_Z_DISTANCE)
  2190.           {
  2191.             LightList = World->GetLightList (); 
  2192.             ObjectList[i]->Project ( Distance );
  2193.             ObjectList[i]->ProcessMeshes ();
  2194.             if (ShadeMethod>SHADE_FLAT)  
  2195.               ObjectList[i]->ComputePointIntensity ( LightList );
  2196.             NumMeshes = ObjectList[i]->GetNumMeshes ();
  2197.             MESH3D *MeshList = ObjectList[i]->GetMeshList ();
  2198.             for (j=0;j<NumMeshes;j++)
  2199.               {
  2200.                 if (MeshList[j].Flags&MESH_VISIBLE)
  2201.                   AddVisibleMesh ( ObjectList[i], &(MeshList[j]) );
  2202.               } // End for
  2203.           } // End if    
  2204.       } // End for
  2205.  
  2206.     SortMesh ();
  2207.     
  2208.     for (i=0;i<NumVisibleMeshes;i++)
  2209.       DisplayMesh ( VisibleMeshes[i].Object, VisibleMeshes[i].Mesh );        
  2210.   } // End of ShowView for G3DENGINE
  2211.  
  2212.  
  2213.  
  2214.